﻿/*
    Nova Code - A script language, parser and recompiler for implementing emulated code instructions
    Copyright (C) 2012  Bryan Perris

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

using System;
using Nova.Parsing;
using System.IO;
using System.Text;
using Nova.Parsing.Constructs;

namespace NovaTester
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=============================");
            Console.WriteLine("=> Nova Code Tester 1.0");
            Console.WriteLine("=============================");
            Console.WriteLine();
            Console.WriteLine("Started Parser {0}", DateTime.Now);
            Console.WriteLine();

            NovaParser novaParser = new NovaParser();
            novaParser.OnParseError += new EventHandler<ParseErrorEventArgs>(novaParser_OnParseError);
            novaParser.OnParseComplete += new EventHandler<ParseCompleteEventArgs>(novaParser_OnParseComplete);

            try
            {
                novaParser.Initialize();

                using (FileStream file = new FileStream(@"..\Samples\Chip8InstructionSet.nova", FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    novaParser.Parse(file, false);
                }
            }
            catch (Exception e)
            {
                WriteException(e);

                if (e.InnerException != null)
                    WriteException(e.InnerException);
            }

            Console.ReadLine();
        }

        static void novaParser_OnParseComplete(object sender, ParseCompleteEventArgs e)
        {
            Console.WriteLine("Completed Parsing! {0}\n", DateTime.Now);

            Console.WriteLine("============================");
            Console.WriteLine("=> Nova Code Parser Results:");
            Console.WriteLine("============================");

            Console.WriteLine();

            foreach (InstructionBlockConstruct instruction in e.InstructionSet)
            {
                Console.WriteLine("Instruction " + instruction.InstructionName);
                DumpStatements(0, instruction.Statements);
                Console.WriteLine();
            }

            Console.WriteLine("============================");
            Console.WriteLine("=> End of Results");
            Console.WriteLine("============================");
        }

        static void DumpStatements(int depth, StatementSet statements)
        {
            if (statements == null)
                return;

            foreach (StatementConstruct statement in statements)
            {
                if (statement.GetType().Equals(typeof(StatementBlock)))
                {
                    StatementBlock block = statement as StatementBlock;
                    DumpStatements(depth + 1, block.Statements);
                }
                else
                {
                    StringBuilder tabs = new StringBuilder();

                    for (int i = 0; i < depth + 1; i++)
                    {
                        tabs.Append("\t");
                    }

                    Console.WriteLine(tabs.ToString() + statement.ToString());
                }
            }
        }

        static void novaParser_OnParseError(object sender, ParseErrorEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(e.ErrorMessage);
            Console.ResetColor();
        }

        static void WriteException(Exception e)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("*** " + e.Message);
            Console.ResetColor();
        }
    }
}
